namespace Xsxiaosa.Net
{
    using System;
    using System.Net;
    using System.Net.Sockets;
// jyj add	
	using System.Text;
//jyj add
	using System.Threading;


    internal abstract class ProxySocks4Base : ProxyBase
    {
        // Methods
        public ProxySocks4Base(Socket socket, bool socks4a) : base(socket)
        {
            this._socks4a = false;
            this._command = 0;
            this._address = ((long) 16777216);
            this._port = 0;
            this._serverName = null;
            this._socks4a = socks4a;
        }

        public override IAsyncResult BeginAccept(AsyncCallback callback, object state)
        {
//jyj modify            IAsyncResult result1;
            base.Begin("Accept", callback, state);
            try
            {
                this.BeginReadReply();
                return this._asyncResult;
            }
            catch (Exception exception1)
            {
                throw base.CancelBegin(exception1);
            }
//jyj modify            return result1;
        }

        public override IAsyncResult BeginConnect(IPEndPoint endPoint, AsyncCallback callback, object state)
        {
            IPEndPoint point1;
            IAsyncResult result1;
            this._command = 1;
            this._address = ProxySocket.GetAddressLong(endPoint.Address);
            this._port = endPoint.Port;
            this._serverName = null;
            base.Begin("Connect", callback, state);
            try
            {
                point1 = ProxySocket.ToEndPoint(this._proxyHost, this._proxyPort);
                if (point1 != null)
                {
                    base.Socket.BeginConnect(point1, new AsyncCallback(this.Connect2), null);
                }
                else
                {
                    Dns.BeginGetHostEntry(this._proxyHost, new AsyncCallback(this.Connect0), null);
                }
                return this._asyncResult;
            }
            catch (Exception exception1)
            {
                throw base.CancelBegin(exception1);
            }
            return result1;
        }

        public override IAsyncResult BeginConnect(string serverName, int serverPort, AsyncCallback callback, object state)
        {
            IPEndPoint point1;
//jyj modify            IAsyncResult result1;
            this._command = 1;
            this._address = ((long) 16777216);
            this._port = serverPort;
            this._serverName = serverName;
            base.Begin("Connect", callback, state);
            try
            {
                point1 = ProxySocket.ToEndPoint(this._proxyHost, this._proxyPort);
                if (point1 != null)
                {
                    if (!this._socks4a && (this._serverName != null))
                    {
                        Dns.BeginResolve(this._serverName, new AsyncCallback(this.Connect1), point1);
                    }
                    else
                    {
                        base.Socket.BeginConnect(point1, new AsyncCallback(this.Connect2), null);
                    }
                }
                else
                {
                    Dns.BeginResolve(this._proxyHost, new AsyncCallback(this.Connect0), null);
                }
                return this._asyncResult;
            }
            catch (Exception exception1)
            {
                throw base.CancelBegin(exception1);
            }
//jyj modify            return result1;
        }

        public override IAsyncResult BeginListen(ProxyBase controlSocket, AsyncCallback callback, object state)
        {
//jyj modify            IAsyncResult result1;
            ProxySocks4Base base1 = ((ProxySocks4Base) controlSocket);
            long num1 = ProxySocket.GetAddressLong(base1._remoteEndPoint.Address);
            if ((num1 & ((long) 16777215)) != ((long) 0))
            {
                this._command = 2;
                this._address = num1;
                this._port = base1._remoteEndPoint.Port;
                this._serverName = null;
            }
            else
            {
                this._command = 2;
                this._address = ((long) 16777216);
                this._port = base1._remoteEndPoint.Port;
                this._serverName = base1._serverName;
            }
            base.Begin("Listen", callback, state);
            try
            {
                base.Socket.BeginConnect(controlSocket.Socket.RemoteEndPoint, new AsyncCallback(this.Connect2), null);
                return this._asyncResult;
            }
            catch (Exception exception1)
            {
                throw base.CancelBegin(exception1);
            }
//jyj modify
//			return result1;
        }

        private void BeginReadReply()
        {
            byte[] numArray1 = new byte[8];
            base.Socket.BeginReceive(numArray1, 0, 8, SocketFlags.None, new AsyncCallback(this.ReadReplyCallback), numArray1);
        }

        private void Command()
        {
            int num1 = (9 + this._proxyUserName.Length);
            if (this._serverName != null)
            {
                num1 += (this._serverName.Length + 1);
            }
            byte[] numArray1 = new byte[((uint) num1)];
            numArray1[0] = 4;
            numArray1[1] = this._command;
            numArray1[2] = ((byte) (this._port >> 8));
            numArray1[3] = ((byte) (this._port & 255));
            numArray1[4] = ((byte) (this._address & ((long) 255)));
            numArray1[5] = ((byte) ((this._address >> 8) & ((long) 255)));
            numArray1[6] = ((byte) ((this._address >> 16) & ((long) 255)));
            numArray1[7] = ((byte) ((this._address >> 24) & ((long) 255)));
            Encoding.ASCII.GetBytes(this._proxyUserName, 0, this._proxyUserName.Length, numArray1, 8);
            if (this._serverName != null)
            {
                Encoding.ASCII.GetBytes(this._serverName, 0, this._serverName.Length, numArray1, (this._proxyUserName.Length + 9));
            }
            base.Socket.Send(numArray1);
        }

        private void Connect0(IAsyncResult result)
        {
            IPHostEntry entry1;
            IPEndPoint point1;
            try
            {
                try
                {
                    entry1 = Dns.EndResolve(result);
                }
                catch (SocketException exception1)
                {
                    base.SetError(new ProxySocketException(Messages.GetString(typeof(ProxySocketStrings), "ResolveFailed"), ProxySocketExceptionStatus.ProxyNameResolutionFailure, exception1));
                    base.Finish();
                    return;
                }
                point1 = new IPEndPoint(entry1.AddressList[0], this._proxyPort);
                if (!this._socks4a && (this._serverName != null))
                {
                    try
                    {
                        Dns.BeginResolve(this._serverName, new AsyncCallback(this.Connect1), point1);
                        return;
                    }
                    catch (SocketException exception2)
                    {
                        base.SetError(new ProxySocketException(Messages.GetString(typeof(ProxySocketStrings), "ResolveFailed"), ProxySocketExceptionStatus.NameResolutionFailure, exception2));
                        base.Finish();
                        return;
                    }
//jyj modify                    return;
                }
                base.Socket.BeginConnect(point1, new AsyncCallback(this.Connect2), null);
            }
            catch (Exception exception3)
            {
                base.SetError(exception3);
                base.Finish();
            }
        }

        private void Connect1(IAsyncResult result)
        {
            IPEndPoint point1;
            IPHostEntry entry1;
            try
            {
                point1 = ((IPEndPoint) result.AsyncState);
                try
                {
                    entry1 = Dns.EndResolve(result);
                }
                catch (SocketException exception1)
                {
                    base.SetError(new ProxySocketException(Messages.GetString(typeof(ProxySocketStrings), "ResolveFailed"), ProxySocketExceptionStatus.NameResolutionFailure, exception1));
                    base.Finish();
                    return;
                }
                this._address = ProxySocket.GetAddressLong(entry1.AddressList[0]);
                this._serverName = null;
                base.Socket.BeginConnect(point1, new AsyncCallback(this.Connect2), null);
            }
            catch (Exception exception2)
            {
                base.SetError(exception2);
                base.Finish();
            }
        }

        private void Connect2(IAsyncResult result)
        {
            try
            {
                base.Socket.EndConnect(result);
            }
            catch (Exception exception1)
            {
                base.SetError(new ProxySocketException(exception1.Message, ProxySocketExceptionStatus.ConnectFailure, exception1));
                base.Finish();
                return;
            }
            try
            {
                this.Command();
                this.BeginReadReply();
            }
            catch (Exception exception2)
            {
                base.SetError(exception2);
                base.Finish();
            }
        }

        private IPEndPoint GetEndPoint(byte[] buffer, int offset)
        {
            int num1 = ((int) ((buffer[offset] << 8) + buffer[(offset + 1)]));
//jyj modify            long num2 = ((long) (((((ulong) (buffer[(offset + 5)] << 24)) + ((long) (buffer[(offset + 4)] << 16))) + ((long) (buffer[(offset + 3)] << 8))) + ((ulong) buffer[(offset + 2)])));
			long num2 = ((long) (((((long) (buffer[(offset + 5)] << 24)) + ((long) (buffer[(offset + 4)] << 16))) + ((long) (buffer[(offset + 3)] << 8))) + ((long) buffer[(offset + 2)])));
            if (num2 == ((long) 0))
            {
                num2 = this._address;
            }
            if (num1 == 0)
            {
                num1 = this._port;
            }
            return new IPEndPoint(num2, num1);
        }

        private void ReadReplyCallback(IAsyncResult result)
        {
            byte[] numArray1;
            int num1;
            object[] objArray1;
            try
            {
                numArray1 = ((byte[]) result.AsyncState);
                num1 = base.Socket.EndReceive(result);
                goto Label_003D;
            Label_001B:
                Thread.Sleep(1);
            Label_0021:
                if (base.Available == 0)
                {
                    goto Label_001B;
                }
                num1 += base.Socket.Receive(numArray1, num1, (8 - num1), SocketFlags.None);
            Label_003D:
                if (num1 < 8)
                {
                    goto Label_0021;
                }
                if (numArray1[1] != 90)
                {
                    objArray1 = new object[1];
                    objArray1[0] = numArray1[1];
                    throw new ProxySocketException(Messages.GetString(typeof(ProxySocketStrings), "Socks4RequestFailed", objArray1), ProxySocketExceptionStatus.ProtocolError);
                }
                this._remoteEndPoint = this.GetEndPoint(numArray1, 2);
                this._asyncResult.SetResult(this._remoteEndPoint);
            }
            catch (Exception exception1)
            {
                base.SetError(exception1);
            }
            finally
            {
                base.Finish();
            }
        }


        // Fields
        private long _address;
        private byte _command;
        private int _port;
        private IPEndPoint _remoteEndPoint;
        private string _serverName;
        private bool _socks4a;
    }}

